﻿using Autofac;
using KJSyncXP.Extensions;
using KJSyncXP.Sqlite.Model;
using KJSyncXP.ViewModels;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Input;

namespace KJSyncXP.Services
{
    public delegate void dgStatusChanged(object sender, string eventArgs);
    public delegate void dgDataReceived(object sender, string eventArgs);
    /// <summary>
    /// 使用方法：
    /// SerialPortService.Instance.Connect();
    /// SerialPortService.Instance.SendCommand("0105000103009CFA");
    /// 
    /// </summary>
    public class SerialPortService : IDisposable
    {
        private static SerialPortService _instance;
        private static readonly object _lock = new object();
        private SerialPort _serialPort;
        private readonly SynchronizationContext _syncContext;
        private static AppConfig _appconfig;

        public event dgStatusChanged StatusChanged;
        public event dgDataReceived DataReceived;

        //public event EventHandler<string> StatusChanged;
        //public event EventHandler<string> DataReceived;

        private SerialPortService()
        {
            _syncContext = SynchronizationContext.Current;
        }
        public static SerialPortService Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lock)
                    {
                        if (_instance == null)
                        {
                            _instance = new SerialPortService();
                        }
                    }
                }
                return _instance;
            }
        }
        ~SerialPortService()
        {

        }
        public string[] GetAvailablePorts()
        {
            return SerialPort.GetPortNames();
        }

        public bool IsOpen => _serialPort?.IsOpen ?? false;

        public void Connect(int baudRate = 9600)
        {
            // 读取AppSettings中的配置
            using (var scope = App._container.BeginLifetimeScope())
            {
                _appconfig = scope.Resolve<AppConfig>();
                string port = _appconfig.comport;
                Connect(port);
                
            }


            // 读取ConnectionStrings中的配置
            //string connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
        }

        public void Connect(string portName, int baudRate = 9600)
        {
            if (IsOpen) return;

            _serialPort = new SerialPort(portName, baudRate)
            {
                Parity = Parity.None,
                DataBits = 8,
                StopBits = StopBits.One,
                Handshake = Handshake.None,
                ReadTimeout = 500,
                WriteTimeout = 500
            };

            _serialPort.DataReceived += SerialPort_DataReceived;

            try
            {
                _serialPort.Open();
                OnStatusChanged($"已连接到 {portName}");
            }
            catch (Exception ex)
            {
                OnStatusChanged($"连接失败: {ex.Message}");
                Dispose();
            }
        }

        public void Disconnect()
        {
            if (!IsOpen) return;

            try
            {
                _serialPort.Close();
                OnStatusChanged("已断开连接");
            }
            finally
            {
                Dispose();
            }
        }

        public void SendCommand(byte command)
        {
            if (!IsOpen)
            {
                OnStatusChanged("串口未连接");
                return;
            }

            try
            {
                byte[] buffer = { command };
                _serialPort.Write(buffer, 0, 1);
                OnStatusChanged($"已发送命令: 0x{command:X2}");
            }
            catch (Exception ex)
            {
                OnStatusChanged($"发送命令失败: {ex.Message}");
            }
        }
        /// <summary>
        /// string hexStr= "0105000B0100BD98"
        /// </summary>
        /// <param name="command"></param>
        public void SendCommand(string command = "0105000B0100BD98")
        {
            if (!IsOpen)
            {
                OnStatusChanged("串口未连接");
                return;
            }

            try
            {
                byte[] buffer = HexConverter.FromHexString(command);
                //byte[] buffer = Convert.FromHexString(command);
                _serialPort.Write(buffer, 0, buffer.Length);
                OnStatusChanged($"已发送命令: 0x{command:X2}");
            }
            catch (Exception ex)
            {
                OnStatusChanged($"发送命令失败: {ex.Message}");
            }
        }
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                string data = _serialPort.ReadExisting();
                if (!string.IsNullOrEmpty(data))
                {
                    _syncContext.Post(_ => DataReceived?.Invoke(this, data), null);
                }
            }
            catch (Exception ex)
            {
                _syncContext.Post(_ => OnStatusChanged($"接收数据错误: {ex.Message}"), null);
            }
        }

        private void OnStatusChanged(string message)
        {
            _syncContext.Post(_ => StatusChanged?.Invoke(this, message), null);
        }

        public void Dispose()
        {
            if (_serialPort != null)
            {
                this.Disconnect();
                _serialPort.DataReceived -= SerialPort_DataReceived;
                _serialPort.Dispose();
                _serialPort = null;
            }
        }
    }
}
